#include "SocketIO.h"
#include <unistd.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <stdio.h>


SocketIO::SocketIO(int fd)
:_fd(fd)
{}

SocketIO::~SocketIO(){
    close(_fd);
}

int SocketIO::readn(char * buf, int len){
    int left = len;
    char* pstr = buf;
    int ret = 0;

    while(left > 0){
        ret = read(_fd,pstr,left);
        //表示读取被信号中断,忽略错误,继续下一次读取。
        if(ret == -1 && errno == EINTR){
            continue;
        }else if(ret == -1)
        {
            perror("read error -1");
            return -1;
        }else if(ret == 0)//表示套接字对端已关闭,跳出循环。
        {
            break;
        }else{
            pstr += ret;
            left += ret;
        }
    }
    return len - left;
    //这个函数确保了即使读取操作被中断，也能正确地读取到所有可用的数据,
    //或者在遇到错误或套接字关闭时停止读取。
}

int SocketIO::writen(const char* buf, int len){
    int left = len;
    const char* pstr = buf;
    while(left > 0) {
        int ret = write(_fd,pstr,left);
        if(ret == -1 && errno == EINTR){
            continue;
        }else if(ret == -1){
            perror("write error -1");
            return -1;
        }else if(ret == 0){
            break;
        }else{
            pstr += ret;
            left -= ret;
        }
    }
    return len - left;
}

int SocketIO::readLine(char* buf, int len){
    int left = len - 1;
    char* pstr = buf;
    int ret = 0,total = 0;
    while(left > 0){
        //MSG_PEEK不会将缓冲区中的数据进行清空,只会进行拷贝操作
        ret = recv(_fd,pstr,left,MSG_PEEK);
        if(-1 == ret && errno == EINTR){
            continue;
        }else if(ret == -1){
            perror("readLine error -1");
            return -1;
        }else if(ret == 0){
            break;
        }else{
            for(int idx = 0;idx < ret ; ++idx){
                if(pstr[idx] == '\n'){
                    int sz = idx + 1;
                    readn(pstr,sz);//调用成员函数readn
                    pstr += sz;
                    *pstr = '\0';
                    return total + sz;
                }
            }
            readn(pstr,ret);
            total += ret;
            pstr += ret;
            left -= ret;
        }
    }
    *pstr = '\0';

    return total - left;
}
